import { Provide } from '@midwayjs/core';
import * as CryptoJS from 'crypto-js';
import axios from 'axios';

const SECRET_KEY = '12345678'; // 密钥，必须和前端一致
const IP_API_URL = 'http://ip-api.com/json/'; // IP 定位服务
const PUBLIC_IP_API_URL = 'http://ipinfo.io/json'; // 获取公网 IP 的 API

@Provide()
export class IPService {
  // 内存缓存 IP 地理信息，避免频繁请求
  private cache = new Map<string, any>();

  // 处理获取时间的业务逻辑
  async getTime(timestamp: string | string[], salt: string | string[]) {
    console.log('timestamp:', timestamp);
    const timestampStr = timestamp.toString();
    const calculatedHash = CryptoJS.MD5(timestampStr + SECRET_KEY).toString();
    console.log('calculatedHash:', calculatedHash);

    // 比对传入的 salt 和服务器计算的 salt
    if (salt !== calculatedHash) {
      console.log('salt 校验失败');
      throw new Error('salt 校验失败');
    }

    // 获取公网 IP
    const ip = await this.getPublicIP(); // 获取公网 IP 地址
    if (!ip) {
      throw new Error('无法获取公网 IP 地址');
    }

    // 获取 IP 地址定位信息
    const geoInfo = await this.getGeoInfo(ip);
    console.log('geoInfo:', geoInfo);

    // 检查 geoInfo 是否有有效的 city 字段
    const location = geoInfo && geoInfo.city ? geoInfo.city : '无法获取城市信息';

    // 获取当地时间（通过定位的时区）
    const localTime = this.getLocalTime(geoInfo.timezone);

    let data = {
      ip,
      location, // 客户端所在城市
      localTime, // 客户端的当地时间
    };
    console.log('data:', data);

    return data;
  }


  // 处理获取本地时间
  async getsysTime(){
    // 获取公网 IP
    const ip = await this.getPublicIP(); // 获取公网 IP 地址
    if (!ip) {
      throw new Error('无法获取公网 IP 地址');
    }

    // 获取 IP 地址定位信息
    const geoInfo = await this.getGeoInfo(ip);
    console.log('geoInfo:', geoInfo);

    // 检查 geoInfo 是否有有效的 city 字段
    const location = geoInfo && geoInfo.city ? geoInfo.city : '无法获取城市信息';

    // 获取当地时间（通过定位的时区）
    const localTime = this.getLocalTime(geoInfo.timezone);

    let data = {
      ip,
      location, // 客户端所在城市
      localTime, // 客户端的当地时间
    };
    console.log('data:', data);

    return data;
  }

  // 通过 IP 地址获取地理位置
  async getGeoInfo(ip: string) {
    if (this.cache.has(ip)) {
      return this.cache.get(ip); // 如果缓存中有该 IP 信息，直接返回
    }

    try {
      const response = await axios.get(`${IP_API_URL}${ip}`);
      const geoInfo = response.data;
      this.cache.set(ip, geoInfo); // 缓存该 IP 的定位信息
      return geoInfo;
    } catch (error) {
      console.error(`IP 地址定位失败: ${error.message}`);
      throw new Error('IP 地址定位失败');
    }
  }

  // 获取公网 IP 地址
  async getPublicIP() {
    try {
      const response = await axios.get(PUBLIC_IP_API_URL);
      console.log('response IP:', response.data);
      return response.data.ip; // 返回公网 IP
    } catch (error) {
      console.error(`获取公网 IP 失败: ${error.message}`);
      throw new Error('获取公网 IP 失败');
    }
  }

  // 获取当地时间，依据时区
  getLocalTime(timezone: string): string {
    try {
      const date = new Date();
      return new Intl.DateTimeFormat('zh-CN', {
        timeZone: timezone,
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit',
        hour12: false, // 使用24小时制
      }).format(date);
    } catch (error) {
      console.error(`获取当地时间失败: ${error.message}`);
      throw new Error('获取当地时间失败');
    }
  }
}
